/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential                                       */
/*                                                                                   */
/* Copyright (c) 2008 by Nuvoton Technology Corporation                              */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/****************************************************************************
 * 
 * FILENAME
 *     spi.c
 *
 * VERSION
 *     1.0
 *
 * DESCRIPTION
 *     This file contains USI library APIs.
 *
 * DATA STRUCTURES
 *     None
 *
 * FUNCTIONS
 *     None
 *
 * HISTORY
  *     10/12/07      Create Ver 1.0
 *
 * REMARK
 *     None
 **************************************************************************/
/* Header files */
#ifdef ECOS
#include "stdlib.h"
#include "string.h"
#include "drv_api.h"
#include "diag.h"
#include "wbtypes.h"
#include "wbio.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#endif

#include "nuc900_reg.h"
#include "nuc900_spi.h"

__align(4096) UCHAR _spi_ucBuffer[64*1024];
UINT8	*_spi_pBuffer;
/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   spiOpen                                                                         */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None				                                                             */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   None.                                                                           */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   This function initial SPI interface and enable interrupt.                       */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
static _spi_init_flag = FALSE;
int spiOpen(VOID)
{
	int status=0;

	if (!_spi_init_flag)
	{
		status = usiInitDevice();
		_spi_init_flag = TRUE;
		_spi_pBuffer = (UINT8 *)((UINT32)_spi_ucBuffer | 0x80000000);
	}
	return status;
}


/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   spiIoctl                                                                        */
/*                                                                                   */
/* Parameters:                                                                       */
/*   sicFeature		SPI_SET_CLOCK.													 */
/*   sicArg0		APB clock by MHz.												 */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   None.                                                                           */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   This function set the USI engine clock.							             */
/*	SIC_SET_CLOCK : sicArg0 used to set clock by MHz								 */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

VOID spiIoctl(INT32 spiFeature, INT32 spicArg0)
{
	switch(spiFeature)
	{
		case SPI_SET_CLOCK:
			usiSetClock(spicArg0);
			break;
	}
}

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   spiRead                                                                         */
/*                                                                                   */
/* Parameters:                                                                       */
/*   spiReadAddress		Flash address to read.										 */
/*   spiLength			length.														 */
/*   spiTargetAddr		The address which data upload to SDRAM.						 */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   0					Success                                                      */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   This function used to get the data from SPI flash					             */
/*-----------------------------------------------------------------------------------*/

INT spiRead(INT32 spiReadAddress, INT32 spiLength, INT32 spiTargetAddr)
{
	return usiRead(spiReadAddress, spiLength, (UINT8 *)spiTargetAddr);
}

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   spiWrite                                                                        */
/*                                                                                   */
/* Parameters:                                                                       */
/*   spiWriteAddress	Flash address to be write.									 */
/*   spiLength			Length.														 */
/*   spiSourcetAddr		The address which data download data from SDRAM.			 */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   0					Success                                                      */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   This function used to write the data to SPI flash					             */
/*-----------------------------------------------------------------------------------*/

INT spiWrite(INT32 spiWriteAddress, INT32 spiLength, INT32 spiSourceAddr)
{
	int i, eraseBlockNo, blockCount, status;

	eraseBlockNo = spiWriteAddress / (64*1024);
	if ((spiWriteAddress % (64*1024)) != 0)
	{
		/* read data back */
		usiRead(eraseBlockNo*64*1024, 64*1024, _spi_pBuffer);
		memcpy(_spi_pBuffer+(spiWriteAddress-(eraseBlockNo*64*1024)), 
				(unsigned char *)spiSourceAddr, (eraseBlockNo+1)*64*1024-spiWriteAddress);
		usiEraseSector(eraseBlockNo*64*1024, 1);
		status = usiWrite(eraseBlockNo*64*1024, 64*1024, (UINT16 *)_spi_pBuffer);
		eraseBlockNo++;
		spiSourceAddr = spiSourceAddr + ((eraseBlockNo+1)*64*1024-spiWriteAddress);

		spiLength = spiLength - ((eraseBlockNo+1)*64*1024-spiWriteAddress);
	}

	blockCount = spiLength / (64*1024);
	for (i=0; i<blockCount; i++)
	{
		usiEraseSector(eraseBlockNo*64*1024, 1);
		status = usiWrite(eraseBlockNo*64*1024, 64*1024, (UINT16 *)spiSourceAddr);

		spiSourceAddr = spiSourceAddr + 64*1024;
		eraseBlockNo++;
	}

	if ((spiLength % (64*1024)) != 0)
	{
		spiLength = spiLength - blockCount*64*1024;

		usiRead(eraseBlockNo*64*1024, 64*1024, _spi_pBuffer);
		memcpy(_spi_pBuffer, (unsigned char *)spiSourceAddr, spiLength);
		usiEraseSector(eraseBlockNo*64*1024, 1);
		status = usiWrite(eraseBlockNo*64*1024, 64*1024, (UINT16 *)_spi_pBuffer);
	}

	return status;
}





